using System;
using System.Data;
using System.Data.SqlClient;
using TDUnit.Common.ScriptExecutionEngine;

namespace TDUnit.MsSql
{
    public class SqlServerScriptExecutionEngine : IScriptExecutionEngine, IDisposable
    {
        #region Private variables

        private readonly SqlConnection connection;
        private readonly SqlCommand command;

        #endregion

        #region Events

        public event EventHandler<ScriptExecutionEngineEventArgs> ExecutedNonQueryScript;
        public event EventHandler<ScriptExecutionEngineEventArgs> ExecutedScalarQueryScript;

        #endregion

        #region Constructors

        public SqlServerScriptExecutionEngine(string connectionString)
        {
            connection = new SqlConnection(connectionString);
            command = new SqlCommand {Connection = connection};
        }

        #endregion

        #region Public methods

        public void ExecuteNonQueryScript(string script)
        {
            SetUpCommand(script);
            command.ExecuteNonQuery();
            OnExecutedNonQueryScript(script);
        }

        public object ExecuteScalarQueryScript(string script)
        {
            SetUpCommand(script);
            var value = command.ExecuteScalar();
            OnExecutedScalarQueryScript(script);
            return value;
        }

        public DataSet ExecuteQuery(string query)
        {
            return ExecuteQuery(query, string.Empty, string.Empty);
        }

        public DataSet ExecuteQuery(string query, string datasetName, string sourceTable)
        {
            SetUpCommand(query);
            var ds = new DataSet(datasetName);
            var da = new SqlDataAdapter(command);
            da.Fill(ds, sourceTable);
            return ds;
        }

        public void Dispose()
        {
            command.Dispose();
            connection.Dispose();
        }

        #endregion

        #region OnEvent Methods

        protected virtual void OnExecutedNonQueryScript(string script)
        {
            if(ExecutedNonQueryScript != null)
                ExecutedNonQueryScript(this, new ScriptExecutionEngineEventArgs(script));
        }

        protected virtual void OnExecutedScalarQueryScript(string script)
        {
            if(ExecutedScalarQueryScript != null)
                ExecutedScalarQueryScript(this, new ScriptExecutionEngineEventArgs(script));
        }

        #endregion

        #region Helper methods

        private void SetUpCommand(string script)
        {
            if(connection.State != ConnectionState.Open)
                connection.Open();
            
            command.CommandText = script;
            command.CommandType = CommandType.Text;
        }

        #endregion
    }
}